#include <stdio.h>
#include <stdlib.h>
#include "TadTablaSimbolo.h"

/* Inicializa la tabla en NULL, y el contador en 0 */
void initTabla (Pila *pila)
{
	pila->tope = NULL;
	pila->tamanio= 0;
}

/* Retorna 1 (true) si la pila esta vacia, 0 (false) de lo contrario */
boolean es_vaciaTabla (Pila *pila)
{
	if (pila == NULL){
		return 1;
 	}else{ 
		return 0;	
	}
}

/* Toma una pila y inserta un nuevo nivel */
void insertarNivel (Pila *pila)
{
	Lista *lista = (Lista *) malloc (sizeof(struct LLista)); 
	initLista(lista);
	ItemPila * nuevo = (ItemPila *) malloc (sizeof(struct ElemPila));
	if (nuevo == NULL){
		printf ("Error: no hay memoria disponible. \n");
		exit(1);
	}
	nuevo->dato = lista;
	nuevo->sig = pila->tope;
	pila->tope = nuevo;
	pila->tamanio++;
}

/* Toma una pila y elimina su tope */
void eliminarNivel (Pila *pila)
{
	if (pila->tamanio == 0){
		printf("Error: no hay nada para eliminar");
		exit(1);
	}else{
		ItemPila * aux;
		aux = pila->tope;
		pila->tope = pila->tope->sig;
		free(aux->dato);
		free(aux);
		pila->tamanio--;
	}
}

/* Toma una pila y la muestra por pantalla */
void mostrarTabla(Pila *pila)
{					
	if (pila->tope == NULL){
		printf("Pila Vacia. Pila == NULL\n");		
		exit(1);
	}
	ItemPila * actual;
	int i;
	actual = pila->tope;
	if (pila->tamanio == 0){
		printf ("Pila vacia\n");
		exit(1);
	}
	for(i=0;i<pila->tamanio;++i){
		mostrarLista(actual->dato);
		actual = actual->sig;
  	}
}


/* Toma una pila y un elemento(lista), y retorna true si el elemento ya pertenece a la pila, de lo contrario false */
boolean perteneceTabla (Pila *pila, Lista*lista)
{
	if ((pila == NULL) || (lista == NULL))
		return 0;
	ItemPila *aux = pila->tope;
	ItemLista *aux2;
	int i, j;
	for (i = 0; i < pila->tamanio; ++i){
		aux2 = lista->primero;
		for (j = 0; j < lista->tamanio; ++j){
			if (perteneceLista(aux->dato,aux2->dato->id) != NULL){
				return 1;
			}
			aux2=aux2->sig;			
		}
		aux=aux->sig;	
		
	}
	return 0; 
}

/* Toma una pila y un elemento (nombre de identificador), y retorna true si el elemento ya pertenece a la pila, de lo contrario false */
Tupla* perteneceTable (Pila *pila, char* id)
{
	if (pila == NULL)
		return NULL;
	ItemPila *aux = pila->tope;
	ItemLista *aux2;
	Tupla* tuple; 
	int i, j;
	for (i = 0; i < pila->tamanio; ++i){
		aux2 = aux->dato->primero;
		for (j = 0; j < aux->dato->tamanio; ++j){
			tuple = perteneceLista(aux->dato,id);
			if ( tuple != NULL){  
				return tuple;
			}
			aux2=aux2->sig;			
		}
		aux=aux->sig;		
	}
	return NULL;
}


/* Toma una pila, y libera todo la memoria que utiliza */
void liberarTabla (Pila *pila)
{
	ItemPila *aux1, *aux2;
	aux1 = pila->tope;
	while (aux1 != NULL) {
		aux2 = aux1->sig;
		free(aux1);
		aux1 = aux2;
	}
}

/* Inicializa el primero de la lista en NULL, y el contador en 0 */
void initLista(Lista *lista)
{
	lista->primero = NULL;
	lista->ultimo = NULL;
	lista->tamanio= 0;
}

/* Retorna 1 (true) si la lista esta vacia, 0 (false) de lo contrario */
boolean es_vaciaLista(Lista *lista)
{
	if (lista == NULL){
		return 1;
 	}else{ 
		return 0;	
	}
}

/* Toma una lista y un id y un char(tipo), e inserta el mismo en ella */
void insertar (Lista *lista, char *var, char *type)
{
	ItemLista *nuevo = (ItemLista *) malloc (sizeof(struct ElemLista));	
	Tupla* aux = (Tupla *) malloc (sizeof(struct Tuplas));

	if ((nuevo == NULL) || (aux == NULL)){	       
		printf ("Error: no hay memoria disponible. \n");
		exit(1);
	}
	aux->id = var;
	aux->tipo = type;
	nuevo->dato = aux;
	

	if (lista->ultimo == NULL){
		nuevo->sig = NULL;
		lista->primero = nuevo;
		lista->ultimo = nuevo;
	}else{
		lista->ultimo->sig = nuevo;
		nuevo->sig = NULL;
		lista->ultimo = nuevo;
	}
	lista->tamanio++; 
}

/* Toma una lista y elimina su primer elemento */
void eliminar (Lista *lista)
{
	if (lista->tamanio == 0){
		printf("Error: no hay nada para eliminar");
		exit(1);
	}else{
		ItemLista * aux;
		aux = lista->primero;
		lista->primero = lista->primero->sig;
		/*free(aux->dato);*/
		free(aux);
		lista->tamanio--;
	}
}

/* Toma una lista y la muestra por pantalla */
void mostrarLista(Lista *lista)
{	
	if ((lista->tamanio == 0) || (lista == NULL)){
		printf ("Lista vacia\n");		
	}else{
		ItemLista * actual;
		int i;
		actual = lista->primero;

		for(i=0;i<lista->tamanio;++i){
			printf("(");	
			printf("%s", actual->dato->id);
			printf(",");	
			printf("%s", actual->dato->tipo);
			printf(")");	
			actual = actual->sig;
	  	}
		printf("\n");
	}
}

/* Toma una lista y un elemento, y retorna true si el elemento ya pertenece a la pila, de lo contrario false */
Tupla* perteneceLista (Lista *lista, char *elem)
{
	if (lista == NULL)
		return NULL;
	ItemLista *aux = lista->primero;
	int i;
	for (i = 0; i< lista->tamanio; ++i){
		if (strcmp(aux->dato->id,elem) == 0)
			return aux->dato;
		aux=aux->sig;	
	}
	return NULL;
}

/* Toma una lista, y libera todo la memoria que utiliza */
void liberarLista(Lista *lista)
{
	ItemLista *aux1, *aux2;
	aux1 = lista->primero;
	while (aux1 != NULL) {
		aux2 = aux1->sig;
		free(aux1);
		aux1 = aux2;
	}
}
